`timescale 1ns/1ps
`default_nettype none
//文件名称：rtl/id_ex_reg.v
//作用:ID/EX 阶段寄存器
module id_ex_reg(
    input  wire        clk,         // 时钟：上升沿触发
    input  wire        rstn,        // 同步复位（低有效）：拉低时清零所有输出寄存器
    input  wire        flush,        // 1=注入气泡（清空控制信号）
    // ---------- 来自 ID 阶段（本拍产生） ----------
    input  wire [31:0] id_pc,       //★ 新增JAL
    input  wire [31:0] id_pc4,      //★ 新增JAL
    input  wire [31:0] id_rdata1,   // 从寄存器堆读到的 rs1 值（ALU 的 A 操作数）
    input  wire [31:0] id_rdata2,   // 从寄存器堆读到的 rs2 值（R 型时作为 ALU 的 B 操作数）
    input  wire [31:0] id_imm,      // I 型指令的有符号扩展立即数（ADDI 用作 ALU 的 B 操作数）
    input  wire [4:0]  id_rs1,       // ★ 新增：源寄存器号 rs1（用于前递比较）
    input  wire [4:0]  id_rs2,       // ★ 新增：源寄存器号 rs2（用于前递比较）
    input  wire [4:0]  id_rd,       // 目的寄存器编号（写回目标寄存器）
    input  wire        id_regwrite, // 写回使能（来自 controller），1 表示本指令将在 WB 写寄存器
    input  wire        id_alusrc_b,   // ALU 第二操作数选择：1=使用立即数（I 型），0=使用 rs2（R 型）
    input  wire [3:0]  id_alu_ctrl, // ALU 功能码：0000=ADD, 0001=SUB（与 alu.v 对应）
    input  wire        id_memread,    // ★ 新增
    input  wire        id_memwrite,   // ★ 新增
    input  wire        id_memtoreg,   // ★ 新增
    input  wire        id_jal,       // ★ 新增JAL
    input  wire        id_branch,    // ★ 新增：BEQ 等分支标志
    input  wire        id_jalr,      // ★ 新增
    input  wire [1:0]  id_alu_src_a_sel,
    input  wire [2:0]  id_branch_type,
    input  wire [1:0]  id_load_size,
    input  wire        id_load_unsigned,
    input  wire [1:0]  id_store_size,
    // ====== 新增：CSR/Trap ======
    input  wire        id_is_csr,          // 本条为 CSR 指令
    input  wire [2:0]  id_csr_funct3,      // CSR funct3（001/010/011/101/110/111）
    input  wire [11:0] id_csr_addr,        // CSR 地址（instr[31:20]）
    input  wire        id_is_ecall,        // ECALL
    input  wire        id_is_mret,         // MRET
    input  wire [4:0]  id_zimm5,           // CSR*I 的 zimm[4:0]（由 ID 从指令取）


    // ---------- 输出到 EX 阶段（下一拍被使用） ----------
    output reg  [31:0] ex_pc,       //★ 新增JAL
    output reg  [31:0] ex_pc4,      //★ 新增JAL
    output reg  [31:0] ex_rdata1,   // 打拍后的 rs1 值 → ALU A
    output reg  [31:0] ex_rdata2,   // 打拍后的 rs2 值 → ALU B（当 ex_alusrc=0）
    output reg  [31:0] ex_imm,      // 打拍后的 I 型立即数 → ALU B（当 ex_alusrc=1）
    output reg  [4:0]  ex_rs1,       // ★ 新增：打拍后的 rs1
    output reg  [4:0]  ex_rs2,       // ★ 新增：打拍后的 rs2
    output reg  [4:0]  ex_rd,       // 打拍后的目的寄存器号 → 后续 EX/MEM、MEM/WB 直至写回
    output reg         ex_regwrite, // 打拍后的写回使能 → 贯穿至 WB 阶段控制寄存器写使能
    output reg         ex_alusrc_b,   // 打拍后的 B 源选择 → EX 阶段选择 ALU 的第二操作数
    output reg  [3:0]  ex_alu_ctrl,  // 打拍后的 ALU 功能码 → EX 阶段选择具体运算
    output reg         ex_memread,    // ★ 新增
    output reg         ex_memwrite,   // ★ 新增
    output reg         ex_memtoreg,    // ★ 新增
    output reg         ex_jal,        // ★ 新增JAL
    output reg         ex_branch,     // ★ 新增BEQ
    output reg         ex_jalr,       // ★ 新增
    output reg  [1:0]  ex_alu_src_a_sel,
    output reg  [2:0]  ex_branch_type,
    output reg  [1:0]  ex_load_size,
    output reg         ex_load_unsigned,
    output reg  [1:0]  ex_store_size,
    // ====== 新增：CSR/Trap ======
    output reg         ex_is_csr,
    output reg  [2:0]  ex_csr_funct3,
    output reg  [11:0] ex_csr_addr,
    output reg         ex_is_ecall,
    output reg         ex_is_mret,
    output reg  [4:0]  ex_zimm5
);

    // 控制信号在 flush/复位时的“安全值”（NOP）
    localparam [3:0]  ALU_ADD = 4'b0000;

    // 时序逻辑：同步复位清零；否则把 ID 阶段的信号在时钟上升沿锁存到 EX 输出
    always @(posedge clk) begin
        if (!rstn) begin
            ex_pc       <=0;        // ★ 新增JAL
            ex_pc4      <=0;        // ★ 新增JAL
            ex_rdata1   <= 32'b0;
            ex_rdata2   <= 32'b0;
            ex_imm      <= 32'b0;
            ex_rs1      <= 5'b0;    //★ 新增
            ex_rs2      <= 5'b0;    //★ 新增
            ex_rd       <= 5'b0;
            ex_regwrite <= 1'b0;
            ex_alusrc_b <= 1'b0;
            ex_alu_ctrl <= ALU_ADD;
            ex_memread  <= 1'b0;
            ex_memwrite <= 1'b0;
            ex_memtoreg <= 1'b0;
            ex_jal      <= 1'b0;         // ★ 新增JAL
            ex_branch   <= 1'b0;         // ★ 新增BEQ
            ex_jalr     <= 1'b0;         // ★ 新增JALR
            ex_alu_src_a_sel<=2'b00; 
            ex_branch_type<=3'b000;
            ex_load_size<= 2'b10; 
            ex_load_unsigned<= 1'b0; 
            ex_store_size<= 2'b10;

            ex_is_csr        <= 1'b0;
            ex_csr_funct3    <= 3'b0;
            ex_csr_addr      <= 12'h000;
            ex_is_ecall      <= 1'b0;
            ex_is_mret       <= 1'b0;
            ex_zimm5         <= 5'b0;
        end else if (flush) begin
            // 注入 NOP：仅清控制信号，数据信号可清零
            ex_pc       <=0;        // ★ 新增JAL
            ex_pc4      <=0;        // ★ 新增JAL
            ex_rdata1   <=0; 
            ex_rdata2   <=0; 
            ex_imm      <=0; 
            ex_rs1      <=0; 
            ex_rs2      <=0; 
            ex_rd       <=0;
            ex_regwrite <=0; 
            ex_alusrc_b <=0; 
            ex_alu_ctrl <=ALU_ADD;
            ex_memread  <=0; 
            ex_memwrite <=0; 
            ex_memtoreg <=0;
            ex_jal<=0;              // ★ 新增JAL
            ex_branch<=0;             // ★ 新增BEQ
            ex_jalr<=0;               // ★ 新增JALR
            ex_alu_src_a_sel<= 2'b00; 
            ex_branch_type<= 3'b000;
            ex_load_size<= 2'b10; 
            ex_load_unsigned<= 1'b0; 
            ex_store_size<= 2'b10;

            ex_is_csr        <= 1'b0;
            ex_csr_funct3    <= 3'b0;
            ex_csr_addr      <= 12'h000;
            ex_is_ecall      <= 1'b0;
            ex_is_mret       <= 1'b0;
            ex_zimm5         <= 5'b0;
        end else begin
            ex_pc       <= id_pc;        // ★ 新增JAL
            ex_pc4      <= id_pc4;       // ★ 新增JAL
            ex_rdata1   <= id_rdata1;
            ex_rdata2   <= id_rdata2;
            ex_imm      <= id_imm;
            ex_rs1      <= id_rs1;   //★ 新增 向下一级传递
            ex_rs2      <= id_rs2;   //★ 新增 向下一级传递
            ex_rd       <= id_rd;
            ex_regwrite <= id_regwrite;
            ex_alusrc_b <= id_alusrc_b;
            ex_alu_ctrl <= id_alu_ctrl;
            ex_memread  <= id_memread;
            ex_memwrite <= id_memwrite;
            ex_memtoreg <= id_memtoreg;
            ex_jal      <=id_jal;             // ★ 新增JAL
            ex_branch   <=id_branch;          // ★ 新增BEQ
            ex_jalr    <= id_jalr;            // ★ 新增JALR
            ex_alu_src_a_sel <=id_alu_src_a_sel; 
            ex_branch_type  <=id_branch_type;
            ex_load_size    <=id_load_size; 
            ex_load_unsigned<=id_load_unsigned; 
            ex_store_size   <=id_store_size;

            ex_is_csr        <= id_is_csr;
            ex_csr_funct3    <= id_csr_funct3;
            ex_csr_addr      <= id_csr_addr;
            ex_is_ecall      <= id_is_ecall;
            ex_is_mret       <= id_is_mret;
            ex_zimm5         <= id_zimm5;
        end
    end
endmodule
